//
//  PrescriptionOrderDetailViewModel.swift
//  EyeVisionForPatients
//
//  Created by PMC on 2021/8/11.
//  Copyright © 2021 QDSG. All rights reserved.
//

import UIKit
import HandyJSON

enum PrescriptionOrderDetailMode {
    case pay, detail
    
    var sections: [PrescriptionOrderDetailSection] {
        switch self {
        case .pay:
            return [
                PrescriptionOrderDetailSection(mode: .receiveType),
                PrescriptionOrderDetailSection(mode: .address),
                PrescriptionOrderDetailSection(mode: .patientInfoForPay),
                PrescriptionOrderDetailSection(mode: .drugs),
                PrescriptionOrderDetailSection(mode: .drugAdvice),
                PrescriptionOrderDetailSection(mode: .doctorInfoForPay)
            ]
        default:
            return [
                PrescriptionOrderDetailSection(mode: .patientInfoForDetail),
                PrescriptionOrderDetailSection(mode: .medicalRecordNo),
                PrescriptionOrderDetailSection(mode: .drugs),
                PrescriptionOrderDetailSection(mode: .doctorInfoForDetail),
                PrescriptionOrderDetailSection(mode: .orderStatus)
            ]
        }
    }
}

class PrescriptionOrderDetailViewModel: NSObject {
    var updateClosure: (() -> ())?
    var changeClosure: (() -> ())?
    
    private var items: [PrescriptionOrderDetailCellViewModel]
    
    private var mode: PrescriptionOrderDetailMode
    
    private var model: PrescriptionOrderDetail = PrescriptionOrderDetail()
    
    var receiveType: PrescriptionOrderReceiveType {
        get { model.receiveType }
        set { model.receiveType = newValue }
    }
    
    init(mode: PrescriptionOrderDetailMode) {
        self.mode = mode
        
        items = mode.sections.map { PrescriptionOrderDetailCellViewModel(with: $0) }
    }
    
    var numberOfSections: Int { items.count }
    
    func viewModel(at section: Int) -> PrescriptionOrderDetailCellViewModel {
        return items[section]
    }
    
    func numberOfRows(in section: Int) -> Int {
        return viewModel(at: section).numberOfRows
    }
    
    func cellHeight(at indexPath: IndexPath) -> CGFloat {
        let viewModel = viewModel(at: indexPath.section)
        return viewModel.cellHeight
    }
    
    func headerHeight(in section: Int) -> CGFloat {
        let viewModel = viewModel(at: section)
        return viewModel.headerHeight
    }
    
    func update(with viewModel: PrescriptionOrderDetailCellViewModel) {
        switch viewModel.mode {
        case .receiveType: receiveType = viewModel.receiveType
        default: break
        }
        handleItems()
    }
    
    func updateReceiver(with vm: FamilyRowViewModel) {
        model.receiverId = vm.receiveId
        model.receiverName = vm.receiveName
        model.receiverPhone = vm.receivePhone
        model.receiverAddress = vm.receiveAddress
        
        handleItems()
    }
    
    var orderId: String {
        get { model.orderId ?? "" }
        set { model.orderId = newValue }
    }
    
    var prescriptionId: String {
        get { model.preId ?? "" }
        set { model.preId = newValue }
    }
    
    var status: PrescriptionOrderStatus? { model.status }
    
    var receiverId: String { model.receiverId ?? "" }
    private var receiverName: String { model.receiverName ?? "" }
    private var receiverPhone: String { model.receiverPhone ?? "" }
    private var receiverAddress: String { model.receiverAddress ?? "" }
    
    var receiverNotEmpty: Bool {
        switch receiveType {
        case .express:
            return !receiverName.isEmpty &&
                !receiverPhone.isEmpty &&
                !receiverAddress.isEmpty &&
                !receiverId.isEmpty
        default:
            return true
        }
    }
    
    var expressNum: String { model.expressNum ?? "" }
    
    var price: String { model.prescriptionAmount ?? "" }
    
    var totalPrice: String { "￥\(model.prescriptionAmount ?? "")" }
    
    var remainPayTime: String { model.remainPayTime }
    
    var cardType: CardType { CardType(rawValue: model.cardType) ?? .unbound }
    var payTimeout: Bool { remainPayTime == "0" }
    /// 剩余支付时间
    var remainPayTimeAttr: NSAttributedString {
        if remainPayTime == "0" {
            let str = "已超时"
            let attributes = [NSAttributedString.Key.foregroundColor: UIColor(hex: "#F54C4C")]
            let attrStr = NSMutableAttributedString(string: str)
            attrStr.setAttributes(attributes, range: NSRange(location: 0, length: str.count))
            return attrStr
        }
        
        let tempStr = Date.timeStampToString(timeStamp: remainPayTime.intValue)
        let str = "请在\(tempStr)内完成支付"
        let attributes = [NSAttributedString.Key.foregroundColor: UIColor(hex: "#F54C4C")]
        let attrStr = NSMutableAttributedString(string: str)
        attrStr.setAttributes(attributes, range: NSRange(location: 2, length: tempStr.count))
        return attrStr
    }
    
    /// 退药快递单
    var backWaybillNo: String = ""
    /// 退药快递公司
    var backLogistics: String = ""
    
    var leftIsHidden: Bool {
        guard let status = status else { return true }
        
        switch status {
        case .waitPay,
             .waitShip,
             .shipped,
             .waitTake,
             .waitSendOut,
             .waitSendOutUnreceived,
             .waitSendOutReceived:  return false
        case .completed:    return receiveType == .express ? false : true
        default:            return true
        }
    }
    
    var bootomViewForDetailHidden: Bool {
        guard let status = status else { return true }
        
        switch status {
        case .unreview,
             .reject,
             .canceled,
             .sendingBack,
             .refunded:    return true
        case .completed:   return receiveType == .express ? false : true
        default:           return false
        }
    }
    
    private func handleItems() {
        items = mode.sections.map { section -> PrescriptionOrderDetailSection in
            var temp = section
            temp.orderDetail = model
            return temp
        }.map { PrescriptionOrderDetailCellViewModel(with: $0) }
    }
}

extension PrescriptionOrderDetailViewModel {
    /// 获取处方订单详情
    func getPrescriptionOrderDetail() {
        HUDTool.showActivity()
        let target = ApiManager.prescriptionOrderDetail(orderId: orderId)
        HttpTool.shared.request(target: target, success: { (json, code) in
            YSGLog("处方药品订单详情: \(json)")
            HUDTool.hideActivity()
            switch code {
            case .failure:
                HUDTool.showError(message: json["message"].description)
            case .success:
                if let model = PrescriptionOrderDetail.deserialize(from: json["data"].description) {
                    self.model = model
                    if self.mode == .pay { self.receiveType = .express }
                    self.handleItems()
                    self.updateClosure?()
                }
            }
        }) { errorMsg in
            HUDTool.hideActivity()
            HUDTool.showError(message: errorMsg)
        }
    }
    
    func getMedicalInsuranceCanPay(success: @escaping (Bool) -> Void) {
        HttpTool.shared.request(api: ApiManager.alipayUserGetSwitch, model: alipayUserGetSwitch.self, completeHandle: {
            switch $0 {
            case .success(let model):
                success(!(model.data?.flag ?? true))
            case .failure(let error):
                error.showToast()
            }
        })
    }
    
    func changePrescriptionOrderStatus(_ status: PrescriptionOrderStatus) {
        HUDTool.showActivity()
        let target = ApiManager.updatePrescriptionOrderStatus(id: prescriptionId, status: status.rawValue, backWaybillNo: backWaybillNo, backLogistics: backLogistics)
        HttpTool.shared.request(target: target) { json, code in
            YSGLog("更新处方订单状态: \(json)")
            HUDTool.hideActivity()
            switch code {
            case .failure:
                HUDTool.showError(message: json["message"].description)
            case .success:
                self.changeClosure?()
            }
        } failure: { error in
            HUDTool.hideActivity()
            HUDTool.showError(message: error)
        }
    }
}

import HandyJSON
struct alipayUserGetSwitch: HandyJSON {
    var flag: Bool = false
}
